// 存放js库代码

var $ = function (args) {
    return new Base(args);
};

// Base 获取网页节点的方法写在构造函数内部
function Base(args){
    this.elements = [];
    // alert(typeof args);
    if (typeof args == 'string') {
        if(args.indexOf(' ')!=-1){
            // css 模拟
            var elements = args.split(' '); // 把节点拆开保存在数组里
            var childElements = []; // 存放临时子节点,解决被覆盖的问题
            var node = []; // 存放父节点, 解决父节点如果也被保存在elements中也会被css等操作的问题
            for (var i = 0; i < elements.length; i++) {
                if (node.length == 0) { // 没有父节点则认为是 document
                    node.push(document);
                }
                switch (elements[i].charAt(0)) {
                    case '#':
                        childElements = [];
                        childElements.push(this.getId(elements[i].substring(1))); // 从第一个字符取到最后一个
                        node = childElements;
                        break;
                    case '.':
                        childElements = [];
                        for (var j = 0; j < node.length; j++) {
                            var temps = this.getClass(elements[i].substring(1),node[j]);
                            for (var k = 0; k < temps.length; k++) {
                                childElements.push(temps[k]);
                            }
                        }
                        node = childElements;
                        break;
                    default:
                        childElements = [];
                        for (var j = 0; j < node.length; j++) {
                            var temps = this.getTagName(elements[i],node[j]);
                            for (var k = 0; k < temps.length; k++) {
                                childElements.push(temps[k]);
                            }
                        }
                        node = childElements;
                        break;
                }
            }
            this.elements = childElements;
        }else{
            // find 模拟
            // alert(args);
            // alert(args.charAt(0));
            switch (args.charAt(0)) {
                case '#':
                    this.elements.push(this.getId(args.substring(1))); // 从第一个字符取到最后一个
                    break;
                case '.':
                    this.elements = this.getClass(args.substring(1));
                    break;
                default:
                    this.elements = this.getTagName(args);
                    break;
            }
        }
        
    }else if (typeof args == 'object') {
        if (args != undefined) { // args 是一个对象 undefined 也是一个对象,所以这里不需要用字符串(也就是不加单引号),区别于typeof返回的是一个字符串
            this.elements[0] = args;
        }
    }else if (typeof args == 'function') {
        this.ready(args);
    }
}

Base.prototype.ready = function (fn) {
    addDomLoaded(fn);
};

Base.prototype.getId = function (id) {
    return document.getElementById(id);
};
Base.prototype.getName = function (name) {
    var tags = document.getElementsByName(name);
    for (var i = 0; i < tags.length; i++) {
        this.elements.push(tags[i]);
    }
    return this;
};
Base.prototype.getClass = function (className, parentNode) {
    var node = null;
    var temp = [];
    if (parentNode != undefined) {
         node = parentNode;
    }else{
        node = document;
    }
    var all = node.getElementsByTagName('*');
    for (var i = 0; i < all.length; i++) {
        // if (all[i].className == className) {
        if ( (new RegExp('(\\s|^)' + className + '(\\s|$)')).test(all[i].className) ) {
            temp.push(all[i]);
        }
    }
    return temp;
};

// 获取首个节点对象
Base.prototype.first = function () {
    return this.elements[0];
};

// 获取末个节点对象
Base.prototype.last = function () {
    return this.elements[this.elements.length-1];
};

// 获取某组节点的数量
Base.prototype.length = function  (){
    return this.elements.length;
};

// 获取某个节点的属性
Base.prototype.attr = function (attr, value) {
    for (var i = 0; i < this.elements.length; i++) {
        if (arguments.length == 1) {
            return this.elements[0].getAttribute(attr);
        } else if(arguments.length == 2) {
            this.elements[i].setAttribute(attr, value);
            return this;
        }
    }
        
};

// 获取某一个节点在整个节点组中的第几个索引
Base.prototype.index = function () {
    var children = this.elements[0].parentNode.children;
    // alert(children.length);
    for (var i = 0; i < children.length; i++) {
        if (this.elements[0] == children[i]) {
            return i;
        }
    }
};

// 设置某一个节点的透明度
Base.prototype.opacity = function (num) {
    for (var i = 0; i < this.elements.length; i++) {
        this.elements[i].style.opacity = num / 100;
        this.elements[i].style.filter = 'alpha(opacity='+ num +')';
    }
    return this;
}

Base.prototype.ge = function (num) {
    return this.elements[num];
};

// 获取某一个节点,并且返回Base对象
Base.prototype.eq = function (num) {
    var element = this.elements[num];
    this.elements = [];
    this.elements.push(element);
    return this;
};

// 获取当前节点的下一个元素
Base.prototype.next = function () {
    for (var i = 0; i < this.elements.length; i++) {
        this.elements[i] =this.elements[i].nextSibling;
        if (this.elements[i]==null) {
            throw new Error('找不到下一个同级元素节点!');
        }
        if (this.elements[i].nodeType == 3 ) { // 节点类型为文本
            this.next();
        }
    }
    return this;
};

// 获取当前节点的上一个元素
Base.prototype.prev = function () {
    for (var i = 0; i < this.elements.length; i++) {
        this.elements[i] =this.elements[i].previousSibling;
        if (this.elements[i]==null) {
            throw new Error('找不到上一个同级元素节点!');
        }
        if (this.elements[i].nodeType == 3 ) { // 节点类型为文本
            this.prev();
        }
    }
    return this;
};

Base.prototype.getTagName = function (tag, parentNode) {
    var temps = [];
    var node = null;
    if (parentNode != undefined) {
        node = parentNode;
    }else{
        node = document;
    }
    var tags = node.getElementsByTagName(tag);
    for (var i = 0; i < tags.length; i++) {
        temps.push(tags[i]);
    }
    return temps;
};

// 给函数添加方法在函数体外添加要加 prototype
Base.prototype.css = function (attr, value) {
    // this.elements.style.attr attr 传递过来的是字符串可能出错,所以用数组的方式
    for (var i = 0; i < this.elements.length; i++) {
        if (arguments.length==1) {
           return getStyle(this.elements[i],attr);
        }
        this.elements[i].style[attr] = value;
    }
    return this;
};

// 添加Class
Base.prototype.addClass = function (className) {
    for (var i = 0; i < this.elements.length; i++) {
        // 避免重复添加class
        if (!hasClass(this.elements[i],className)) {
            this.elements[i].className += ' ' + className;
        }
    }
    return this;
};

// 移除Class
Base.prototype.removeClass = function (className) {
    for (var i = 0; i < this.elements.length; i++) {
        // 避免重复添加class
        if (hasClass(this.elements[i],className)) {
            this.elements[i].className = this.elements[i].className.replace(new RegExp('(\\s|^)' + className + '(\\s|$)'),' ');
        }
    }
    return this;
};

// 设置link 或 style 中的 css规则
Base.prototype.addRule = function (num,selectorText,cssText,position) {
    var sheet = document.styleSheets[num];
    inserRule(sheet,selectorText,cssText,position);
    return this;
};

// 移除link或style中的css规则
Base.prototype.removeRule = function (num,position) {
    var sheet = document.styleSheets[num];
    deleteRule(sheet,position);
    return this;
};

// 获取表单字段元素
Base.prototype.form = function (name) {
    for (var i = 0; i < this.elements.length; i++) {
        this.elements[i] = this.elements[i][name];
    }
    return this;
};

// 获取和设值表单字段元素的设置值
Base.prototype.value = function (str) {
    for (var i = 0; i < this.elements.length; i++) {
        if (arguments.length==0) {
            return this.elements[i].value;
        }
        this.elements[i].value = str;
    }
    return this;
};

// 设置innerHTML
Base.prototype.html = function (value) {
    for (var i = 0; i < this.elements.length; i++) {
        if (arguments.length==0) {
            return this.elements[i].innerHTML;
        }else{
            this.elements[i].innerHTML = value;
        }
    }
    return this;
};

// 设置innerText
Base.prototype.text = function (str) {
    for (var i = 0; i < this.elements.length; i++) {
        if (arguments.length==0) {
            return getInnerText(this.elements[i]);
        }else{
            setInnerText(this.elements[i],str);
        }
    }
    return this;
};

// 设置事件发生器
Base.prototype.bind = function (event,fn) {
    for (var i = 0; i < this.elements.length; i++) {
        addEvent(this.elements[i],event,fn);
    }
    return this;
};
// 设置鼠标移入移出方法
Base.prototype.hover = function (over, out) {
    for (var i = 0; i < this.elements.length; i++) {
        /* this.elements[i].onmouseover = over;
        this.elements[i].onmouseout = out; */
        addEvent(this.elements[i],'mouseover',over);
        addEvent(this.elements[i],'mouseout',out);
    }
    return this;
};

Base.prototype.toggle = function () {
    for (var i = 0; i < this.elements.length; i++) {
        // tog(this.elements[i],arguments);
        // 闭包实现
        (function (element, args) {
            var count = 0; // 函数中的变量就是局部变量
            // var args = arguments;
            addEvent(element,'click',function () {
                args[ (count++) % args.length].call(this); // this = 222 this.elements[i]
            });
        })(this.elements[i],arguments);
    }
    return this;
};

Base.prototype.show = function () {
    for (var i = 0; i < this.elements.length; i++) {
        this.elements[i].style.display = 'block';
    }
    return this;
};

Base.prototype.hide = function () {
    for (var i = 0; i < this.elements.length; i++) {
        this.elements[i].style.display = 'none';
    }
    return this;
};

// 设置物体居中
Base.prototype.center = function (width, height) {
    var top = (getInner().height - height)/2;
    var left = (getInner().width - width)/2;
    for (var i = 0; i < this.elements.length; i++) {
        this.elements[i].style.top = top + 'px';
        this.elements[i].style.left = left + 'px';
    }
    return this;
};

// 设置窗口重画函数
Base.prototype.resize = function (fn) {
    for (var i = 0; i < this.elements.length; i++) {
        var element = this.elements[i];
        addEvent(window, 'resize', function () {
            fn();
            if (element.offsetLeft > this.getInner().width - element.offsetWidth) {
                element.style.left = this.getInner().width - element.offsetWidth + 'px';
            }
            if (element.offsetTop > this.getInner().height - element.offsetHeight) {
                element.style.top = this.getInner().height - element.offsetHeight + 'px';
            }
        })
        this.elements[i];
    }
    return this;
};

// 锁屏功能
Base.prototype.lock = function () {
    for (var i = 0; i < this.elements.length; i++) {
        // this.elements[i].style.width = document.documentElement.clientWidth + 'px'; // 这个火狐会有一个滚动条白边
        this.elements[i].style.width = getInner().width + 'px'; // 这个可以解决火狐的白边,但 IE不支持,需要做跨浏览器支持
        // this.elements[i].style.height = document.documentElement.clientHeight + 'px';
        this.elements[i].style.height = getInner().height + 'px';
        this.elements[i].style.display = 'block';
        document.documentElement.style.overflow = 'hidden';
        // 可以阻止safari 和chrome 这个老版的没有办法验证
        // 这样IE8登录框里面的文字选不中了
       /*  addEvent(this.elements[i],'mousedown',function (e) {
            e.preventDefault();
            addEvent(document,'mousemove',function (e) {
                e.preventDefault();
            });
        }) */
        addEvent(window, 'scroll', scrollTop);
    }
    return this;
};

// 解锁功能
Base.prototype.unlock = function () {
    for (var i = 0; i < this.elements.length; i++) {
        this.elements[i].style.display = 'none';
        document.documentElement.style.overflow = 'auto';
        removeEvent(window, 'scroll', scrollTop);
    }
    return this;
};

Base.prototype.click = function (fn) {
    for (var i = 0; i < this.elements.length; i++) {
        this.elements[i].onclick = fn;
    }
    return this;
};

// 插件入口
/* name 插件名称
fn 插件函数
 */
Base.prototype.extend = function (name,fn) {
    Base.prototype[name] = fn;
};

// 设置CSS子节点选择器
Base.prototype.find = function(str) {
    var childElements = [];
    for (var i = 0; i < this.elements.length; i++) {
        switch (str.charAt(0)) {
            case '#':
                childElements.push(this.getId(str.substring(1)));
                break;
            case '.':            
                var temps = this.getClass(str.substring(1),this.elements[i]);
                for (var j = 0; j < temps.length; j++) {
                    childElements.push(temps[j]);
                }
                break;
            default:
                /* var tags = this.elements[i].getElementsByTagName(str);
                for (var j = 0; j < tags.length; j++) {
                    childElements.push(tags[j]);
                } */
                var temps = this.getTagName(str,this.elements[i]);
                for (var j = 0; j < temps.length; j++) {
                    childElements.push(temps[j]);
                }
                break;
        }
    }
    this.elements = childElements;
    return this;
};

// 设置动画
Base.prototype.animate = function (obj) {
    for (var i = 0; i < this.elements.length; i++) {
        var element = this.elements[i];
        var attr = obj['attr'] == 'x' ? 'left' : obj['attr'] == 'y' ? 'top' : 
            obj['attr'] == 'w' ? 'width' : obj['attr'] == 'h' ? 'height' :
            obj['attr'] == 'o' ? 'opacity' : obj['attr'] != undefined ? obj['attr'] : 'left';                     // 可选left和top两种值,不传默认left
        // 设置 start 在opacity时不为空
        var start = obj['start'] != undefined ? obj['start'] :
            attr == 'opacity' ? parseFloat(getStyle(element, attr))*100 :
                parseInt(getStyle(element, attr)); // 可选,默认为css起始位置
        var t = obj['t'] != undefined ? obj['t'] : 50; // 可选,默认为50毫秒执行一次
        var step = obj['step'] != undefined ? obj['step'] : 10; // 可选,默认为每次运行10像素
        var alter = obj['alter'];
        var target = obj['target'];
        var mul = obj['mul'];

        var speed = obj['speed'] != undefined ? obj['speed'] : 6; // 可选,默认缓冲速度为6
        var type = obj['type'] == 0 ? 'constant' : obj['type'] == 1 ? 'buffer' : 'buffer'; // 可选,0表示匀速, 1和默认为缓冲

        // 如果只有目标或增量 有哪个用哪个,同时有用目标量,没有报错
        if (alter != undefined && target == undefined) {
            target = alter + start;
        } else if (alter == undefined && target == undefined && mul==undefined) {
            throw new Error('alter增量或target或mul目标必须传一个')
        } 
        if (start > target) {
            step = -step;
        }
        if (attr == 'opacity') {
            element.style.opacity = parseInt(start) / 100;
            element.style.filter = 'alpha(opacity=' + parseInt(start) + ')';
        } 
        // 这里不需要用到了

        if (mul == undefined) {
            mul = {};
            mul[attr] = target;
        }
        // alert(start);
        clearInterval(element.timer);
        element.timer = setInterval(function () {
            var flag = true; // 是否所有的动画都执行完毕
            for (var i in mul) {
                /*  console.log(i);
                 console.log(mul[i]); */
                attr = i == 'x' ? 'left' : i == 'y' ? 'top' : i == 'w' ? 'width' : i == 'h' ? 'height' : i == 'o' ? 'opacity' : i!=undefined ? i : 'left' ;
                target = mul[i];
                // document.getElementById('aaa').innerHTML += element.style.opacity + '<br>';
                if (type == 'buffer') {
                    step = attr == 'opacity' ? (target - parseFloat(getStyle(element, attr)) * 100) / speed :
                        (target - parseInt(getStyle(element, attr))) / speed;
                    // step = Math.ceil(step);// floor 当 step为0.5的时候会停止,所以用ceil
                    // step = Math.floor(step);
                    step = step > 0 ? Math.ceil(step) : Math.floor(step);
                    // console.log(step+'...');
                }

                if (attr == 'opacity') {
                    var temp = parseFloat(getStyle(element, attr)) * 100;
                    if (step == 0) {
                        setOpacity();
                    } else if (step > 0 && Math.abs(parseFloat(getStyle(element, attr)) * 100 - target) <= step) {
                        setOpacity();
                    } else if (step < 0 && parseFloat(getStyle(element, attr)) * 100 - target <= Math.abs(step)) {
                        setOpacity();
                    } else {
                        element.style.opacity = parseInt(temp + step) / 100;
                        element.style.filter = 'alpha(opacity=' + parseInt(temp + step) + ')';
                    }
                    if (parseInt(target) != parseInt(parseFloat(getStyle(element, attr)) * 100 )) {
                        flag = false;
                    }
                } else {
                    if (step == 0) {
                        setTarget();
                    } else if (step > 0 && Math.abs(parseInt(getStyle(element, attr)) - target) <= step) {
                        setTarget();
                    } else if (step < 0 && parseInt(getStyle(element, attr)) - target <= Math.abs(step)) {
                        setTarget();
                    } else {
                        element.style[attr] = Math.ceil(parseFloat(getStyle(element, attr)) + Math.ceil(step)) + 'px';
                    }
                    if (parseInt(target)!=parseInt(getStyle(element,attr))) {
                        flag = false;
                    }
                }
            }
            if (flag==true) {
                clearInterval(element.timer);
                if (obj.fn != undefined) {
                    obj.fn();
                }
            }
        }, t);

        function setTarget() {
            element.style[attr] = target + 'px';
        }

        function setOpacity() {
            element.style.opacity = parseInt(target) / 100;
            element.style.filter = 'alpha(opacity=' + parseInt(target) + ')';
        }
    }
    return this;
};

